#include "stdafx.h"
#include "OcclusionXAPO.h"

OcclusionXAPO::OcclusionXAPO(const XAPO_REGISTRATION_PROPERTIES *pRegProperties, BYTE* pParameters, UINT32 ParametersSize, BOOL fProducer, WAVEFORMATEXTENSIBLE* pWfx):CXAPOParametersBase(pRegProperties, pParameters, ParametersSize, fProducer)
{
  

  occlusionLevel = 0.8f;
  channels = pWfx->Format.nChannels;
  bytesPerSample = ( (pWfx->Format.wBitsPerSample) >> 3);

  for(int i = 0; i <= 5; i++)
	  lastOutput[i] = 0.0f;

}

STDMETHODIMP OcclusionXAPO::LockForProcess(UINT32 InputLockedParameterCount, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputProcessParameters, UINT32 OutputLockedParameterCount, XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputProcessParameters) {
  channels = (&pInputProcessParameters)[0]->pFormat->nChannels;
  bytesPerSample = ((&pInputProcessParameters)[0]->pFormat->wBitsPerSample >> 3);

  
  return CXAPOBase::LockForProcess(
    InputLockedParameterCount, 
    pInputProcessParameters, 
    OutputLockedParameterCount, 
    pOutputProcessParameters);
}

STDMETHODIMP_(void) OcclusionXAPO::Process(UINT32 InputProcessParameterCount,const  XAPO_PROCESS_BUFFER_PARAMETERS* pInputProcessParameters, UINT32 OutputProcessParameterCount, XAPO_PROCESS_BUFFER_PARAMETERS* pOutputProcessParameters, BOOL IsEnabled) {
  
  CXAPOParametersBase::BeginProcess();
  void* pInputBuffer = pInputProcessParameters[0].pBuffer;
  assert(pInputBuffer != NULL);

  void* pOutputBuffer = pOutputProcessParameters[0].pBuffer;
  assert(pOutputBuffer != NULL);
    
  // one-pole low pass:
  float sampleRate = 48000.0f;
  float cutOffFreq = 500.0f;
  float lowFrequencyRatio = 0.25f; // ie. attenuate -2.5db at f=0


  if(occlusionLevel<0.01f) occlusionLevel = 0.01f;
  if(occlusionLevel>0.99f) occlusionLevel = 0.99f;

  double PI = 3.141592654; 
  float w = 2.0f  * cutOffFreq / sampleRate;
  float g = (1.0f-occlusionLevel);
  float cosw = cos(w);
  float a = (1.0f - g*cosw - sqrt(2.0f*g*(1.0f-cosw)-g*g*(1.0f-cosw*cosw))) / (1.0f-g);
  float k = g;

    for(int i=0; i<channels; i++) {
    for(int j=0; j<pInputProcessParameters[0].ValidFrameCount; j++) {
            float sample = ((float*)pInputBuffer)[i*pInputProcessParameters[0].ValidFrameCount + j];
      lastOutput[i] = (1.0f-a) * sample + a*lastOutput[i];
      ((float*)pOutputBuffer)[i*pInputProcessParameters[0].ValidFrameCount + j] = lastOutput[i];
    }
  }

  pOutputProcessParameters[0].ValidFrameCount = pInputProcessParameters[0].ValidFrameCount; 
  pOutputProcessParameters[0].BufferFlags     = pInputProcessParameters[0].BufferFlags;

  CXAPOParametersBase::EndProcess();
}